package service

import (
	"context"
	"github.com/pkg/errors"
	"github.com/spf13/cast"
	"log"
	"nearby/biz/common"
	"nearby/biz/dal/db/po"
	"nearby/biz/dal/db/repo"
	"nearby/biz/domain/entity"
	domainService "nearby/biz/domain/service"
	"nearby/biz/model"
	"nearby/biz/model/vo"
)

type GetCommentsService struct {
}

func (ss *GetCommentsService) checkParam(ctx context.Context, req *model.GetCommentsRequest) error {
	paramErr := errors.New("param check fail")
	if req.Limit <= 0 {
		req.Limit = 40
	}
	if req.Limit >= 100 {
		return errors.New("单次查询超出限制")
	}
	if cast.ToInt64(req.EntityID) == 0 {
		return paramErr
	}
	if req.EntityType == "" {
		return paramErr
	}
	return nil
}

func (ss *GetCommentsService) Execute(ctx context.Context, req *model.GetCommentsRequest) (*model.GetCommentsResponse, error) {
	log.Printf("req is: %+v", req)
	err := ss.checkParam(ctx, req)
	if err != nil {
		return nil, common.NewBizErr(common.BizErrCode, err.Error(), err)
	}
	switch req.EntityType {
	case common.EntityTypeMoment:
		return ss.GetCommentsOfMoment(ctx, req)
	case common.EntityTypeComment:
		return ss.GetCommentsOfComments(ctx, req)
	default:
		return nil, common.NewBizErr(common.BizErrCode, "未知的实体类型", nil)
	}
}

func (ss *GetCommentsService) GetCommentsOfMoment(ctx context.Context, req *model.GetCommentsRequest) (*model.GetCommentsResponse, error) {
	commentDomainService := domainService.CommentService{}
	commentEntities, total, err := commentDomainService.GetComments(ctx, domainService.GetCommentsRequest{
		MomentID: cast.ToInt64(req.EntityID),
		Limit:    req.Limit,
		Offset:   req.Offset,
	})
	if err != nil {
		return nil, common.NewBizErr(common.BizErrCode, "获取评论列表失败", err)
	}
	err = ss.LoadInfos(ctx, commentEntities)
	if err != nil {
		log.Printf("GetCommentsService report, ss.LoadInfos fail, err:%+v", err)
	}
	return &model.GetCommentsResponse{
		Meta:     common.MetaOk,
		Comments: ss.ToCommentVos(commentEntities),
		Total:    total,
	}, nil
}

func (ss *GetCommentsService) GetCommentsOfComments(ctx context.Context, req *model.GetCommentsRequest) (*model.GetCommentsResponse, error) {
	// 一期不做
	return nil, common.NewBizErr(common.BizErrCode, "一期不做这个", nil)
}

func (ss *GetCommentsService) LoadInfos(ctx context.Context, entities []*entity.Comment) error {
	err := ss.LoadUserInfos(ctx, entities)
	if err != nil {
		return err
	}
	ss.LoadUserLikeInfos(ctx, entities)
	return nil
}

func (ss *GetCommentsService) ToCommentVos(entities []*entity.Comment) []*vo.Comment {
	vos := make([]*vo.Comment, len(entities))
	for i := range vos {
		vos[i] = entities[i].ToVo()
	}
	return vos
}

// LoadUserInfos 这块代码和Moment装载用户信息的逻辑有很大的相似性
func (ss *GetCommentsService) LoadUserInfos(ctx context.Context, commentEntities []*entity.Comment) error {
	userIDs := ss.GetUserIDs(ctx, commentEntities)
	// 1. 获取userPos
	userRepo := repo.NewUserRepo(ctx)
	userPos, err := userRepo.GetUserPos(ctx, userIDs)
	if err != nil {
		return err
	}
	// 2. 整合到userMap里
	userMap := make(map[int64]*po.User)
	for i := range userPos {
		userMap[userPos[i].UserID] = userPos[i]
	}
	// 3. 将用户信息装载到commentEntities
	for i := range commentEntities {
		userID := commentEntities[i].User.UserID
		info := userMap[userID]
		if info != nil {
			commentEntities[i].User.Nickname = userMap[userID].Nickname
			commentEntities[i].User.HeadURL = userMap[userID].HeadURL
		}
	}
	return nil
}

func (ss *GetCommentsService) GetUserIDs(ctx context.Context, entities []*entity.Comment) (userIDs []int64) {
	userIDs = make([]int64, 0)
	bitMap := make(map[int64]bool)
	for i := range entities {
		bitMap[entities[i].User.UserID] = true
	}
	for userID := range bitMap {
		userIDs = append(userIDs, userID)
	}
	return userIDs
}

func (ss *GetCommentsService) LoadUserLikeInfos(ctx context.Context, entities []*entity.Comment) {

}
